/**
 * Copyright (c) 2009  Collaborative Development Group, C.S. Dept., University of Bari
 *
 * All rights reserved. This program and the accompanying materials are made available under
 * the terms of the Eclipse Public License v1.0  which accompanies this distribution, and is 
 * available at http://www.eclipse.org/legal/epl-v10.html
 */
package it.uniba.di.cdg.penelope.ui.eclipse;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.same;
import static org.mockito.Mockito.verify;
import it.uniba.di.cdg.penelope.presenterfirst.SUT;
import it.uniba.di.cdg.penelope.ui.lnf.EclipseUIHelper;
import it.uniba.di.cdg.penelope.ui.test.integration.TestPerspective;
import it.uniba.di.cdg.penelope.ui.test.integration.TestView;

import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveListener3;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.hamcrest.Description;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.internal.matchers.TypeSafeMatcher;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

/**
 * Tests for {@link EclipseUIHelper}
 */
@RunWith( MockitoJUnitRunner.class )
public class EclipseUIHelperTests {
	
	@Mock private IPerspectiveListener3 perspectiveListener;
	
	@SUT
	private EclipseUIHelper helper;
	
	@Before
	public void setupEclipseUIHelper() {
		helper = new EclipseUIHelper( workbench() );

		activeWorkbenchWindow().addPerspectiveListener( perspectiveListener );
	}
	
	@After
	public void removeListeners() {
		activeWorkbenchWindow().removePerspectiveListener( perspectiveListener );
	}
	
	@Test
	public void shouldSwitchPerspective() {
		helper.switchPerspective( TestPerspective.ID );
		
		verify( perspectiveListener ).perspectiveActivated( 
				same( activeWorkbenchPage() ), 
				any( IPerspectiveDescriptor.class ) );
	}

	@Test
	public void shouldClosePerspective() {
		helper.switchPerspective( TestPerspective.ID );
		
		helper.closePerspective( TestPerspective.ID );

		// XXX Better matching on the descriptor and id. See PerspectiveMatcher for an idea
		//PerspectiveMatcher.withPerspective( TestPerspective.ID );

		verify( perspectiveListener ).perspectiveClosed( 
				same( activeWorkbenchPage() ), 
				any( IPerspectiveDescriptor.class ) );
	}

	@Test
	public void shouldShowView() {
		helper.showView( TestView.VIEW_ID );

		// XXX Better matching on the descriptor and id.
		verify( perspectiveListener ).perspectiveChanged( 
				same( activeWorkbenchPage() ),  
				any( IPerspectiveDescriptor.class ), 
				eq( IWorkbenchPage.CHANGE_VIEW_SHOW ) );
	}
	
	@Test
	public void shouldHideView() {
		helper.hideView( TestView.VIEW_ID );

		// XXX Better matching on the descriptor and id.
		verify( perspectiveListener ).perspectiveChanged( 
				same( activeWorkbenchPage() ), 
				any( IPerspectiveDescriptor.class ), 
				eq( IWorkbenchPage.CHANGE_VIEW_HIDE ) );
	}
	
	// TODO Fix or remove this!
	private static class PerspectiveMatcher extends TypeSafeMatcher<IPerspectiveDescriptor> {
		private final String perspectiveId;

		/**
		 * @param perspectiveId
		 */
		public PerspectiveMatcher( String perspectiveId ) {
			this.perspectiveId = perspectiveId;
		}

		/* (non-Javadoc)
		 * @see org.junit.internal.matchers.TypeSafeMatcher#matchesSafely(java.lang.Object)
		 */
		@Override
		public boolean matchesSafely( IPerspectiveDescriptor item ) {
			return perspectiveId.equals( item.getId() );
		}

		/* (non-Javadoc)
		 * @see org.hamcrest.SelfDescribing#describeTo(org.hamcrest.Description)
		 */
		@Override
		public void describeTo( Description matchDescription ) {
			matchDescription.appendText( "A perspective with id " ).appendValue( perspectiveId );
		}
		
		public static PerspectiveMatcher withPerspective( String perspectiveId ) {
			return new PerspectiveMatcher( perspectiveId );
		}
		
	};
	
	
	/**
	 * @return
	 */
	protected IWorkbenchPage activeWorkbenchPage() {
		return activeWorkbenchWindow().getActivePage();
	}

	protected IWorkbenchWindow activeWorkbenchWindow() {
		return workbench().getActiveWorkbenchWindow();
	}
	
	/**
	 * @return
	 */
	protected IWorkbench workbench() {
		return PlatformUI.getWorkbench();
	}

}
